package sysUtil

import com.github.drinkjava2.jdialects.Dialect
import initConfig.SysInitData
import net.sf.json.JSONObject
import org.apache.poi.util.TempFile
import org.codehaus.groovy.grails.plugins.datasource.DataSourceUtils
import org.jsoup.Jsoup
import org.jsoup.nodes.Document
import xdTool.XdWidget
import xdTool.XdWidgetPanel

import javax.servlet.http.HttpServletRequest
import java.sql.Clob
import java.text.SimpleDateFormat

/**
 * Created by Administrator on 2018-05-15.
 */
class SysCommUtil {

    public final static DateFormat_YYYYMMDD_hh24miss = "yyyy-MM-dd HH:mm:ss"
    public final static DateFormat_YYYYMMDD = "yyyy-MM-dd"
    public final static DateFormat_YYYYMM = "yyyy-MM"

    /**
     * 根据日期样式，获取转换字符串 日期
     * @param format
     * @param target
     * @return
     */
    public static Date getDateByFormatAndStr(String format,Object target){
        Date date

        SimpleDateFormat sdf = new SimpleDateFormat(format)
        if(target instanceof String){
            date = sdf.parse(target)
        }else if(target instanceof Date){
            date = sdf.parse(sdf.format(target))
        }

        return date

    }

    public static Calendar getCalendar(){
        return Calendar.newInstance()
    }



    /**
     *
     * @param obj 对象转Map
     * @return
     * @throws Exception
     */
    public static HashMap<String, Object> objectToMap(Object obj)
            throws Exception {
        if(obj == null)
            return null;
        return new org.apache.commons.beanutils.BeanMap(obj);
    }

    /**
     * Map 转对象
     * @param map
     * @param beanClass
     * @return
     */
    public  static Object mapToObject(Map map,Class<?> beanClass){
        if (map == null){
            return null;
        }
        Object obj = beanClass.newInstance();
        org.apache.commons.beanutils.BeanUtils.populate(obj, map);
        return   obj
    }
    /**
     * 主要用于转换domain产生的list转JSON用
     * @param obj
     * @return
     */
    public static List domainListToList(List obj){
        def result = []
        if(obj){
            obj.each {
                result.add(domainToMap(it))
            }
        }
        return result
    }


    /**
     * 主要将list、数组转换成sql，以指定符号分割'1','2','3',
     * @param list
     * @param split
     * @return
     */
    public static String listToString(List data,String head,String tail,String flag){
        StringBuffer s = new StringBuffer("")
        String r = ''
        if(data){
            def size = data.size()
            s.append(head?:"" )
            for(def i=0;i<data.size();i++){
                if(i != (size-1)){
                    s.append("${data.get(i)?:""}${flag?:","}");
                }else{
                    s.append("${data.get(i)?:""}${tail?:""}");
                }
            }
        }
        return  s.toString()
    }

    public static String listToString(List data){
         return listToString(  data,null,null,",")
    }

    /**
     * 根据父节点，生成树
     * @param parent list
     * @param children list
     * @param id :node id
     * @param pid :parent node name
     * @param children :node name
     */
    static List listFindTree(List parentList,List childList,String id,String pid,String children){
        def newChildList = (List)childList.clone()
        def result = []
        parentList.each { parent ->
            def a1 =  (parent instanceof  java.util.Map)? parent:parent.getProperties()
            def a = copyMap(a1)

            a.put(id,a1.get(id))
            a.put( pid ,a1.get(pid))
            a.put(children,[])

             if( childList."${pid}".contains( a.get(id)) ){
                 def tmp = []
                 childList.each {child ->
                     def b1 = (child instanceof  java.util.Map)? child:child.getProperties()
                     def b = copyMap(b1)
                     b.put(id,b1.get(id))
                     b.put(pid,b1.get(pid))
                     b.put(children,[])

                     //println "a.get(id) == b.get(pid):${a.get(id) == b.get(pid)}"
                     if( a.get(id) == b.get(pid) ){
                         tmp.add(b)
                         newChildList.remove(child)
                     }
                 }
                 def c = listFindTree(tmp,  newChildList,  id,  pid,  children)
                 a.put(children,c)
            }
            result.add(a)
        }
        return  result
    }

    /**
     * copy Map
     * @param self
     * @return Map
     */

    public static Map copyMap(Object self){
        def map = [:]
        try {
            if(!self){
                return map
            }

            if( !(self instanceof java.util.Map) ){
                self = self.getProperties()
            }

            self.each {key,value ->
                if( value instanceof java.sql.Clob || value instanceof oracle.sql.CLOB){
                    //println "key:${key} value:${value.getClass()} ${value.toString()}"
                    value = SysCommUtil.Clob2String(value)
                }

                map.put(key,value)
            }
            map.remove("map")
            map.remove("class")
            map.put("id",self?.id )
        }catch (Exception e){
            //print("Object has no id property...")
        }finally{
            return map
        }
    }

    /**
     * 用于将对象list转换Map list
     * @param list
     * @return
     */
    static List copyMapList(List list){
        def result = []
        list.each {
            result.add( copyMap(it))
        }
        return result
    }


    /**
     * 用于将domain转Map
     * @param self
     * @return
     */
    public static Map domainToMap(Object self){
        if(self){
            def map = SysCommUtil.objectToMap(self)
            //println map
            map.remove("class")
            map.remove("properties")
            map.remove("metaClass")
            map.remove("map")
            return map
        }
        return null
    }

    public static final UNDERLINE = "_"
    /**
     * 驼峰字符串转换下划线
     * @param param
     * @return
     */
    public static String camelToUnderline(String param) {
        if (param == null || "".equals(param.trim())) {
            return "";
        }
        int len = param.length();
        StringBuilder sb = new StringBuilder(len);
        for (int i = 0; i < len; i++) {
            char c = param.charAt(i);
            if (Character.isUpperCase(c)) {
                sb.append(UNDERLINE);
                sb.append(Character.toLowerCase(c));
            } else {
                sb.append(c);
            }
        }
        return sb.toString();
    }

    /**
     * 下划线格式字符串转换为驼峰格式字符串
     *
     * @param param
     * @return
     */
    public static String underlineToCamel(String param) {
        if (param == null || "".equals(param.trim())) {
            return "";
        }else{
            param = param.toLowerCase()
        }
        int len = param.length();
        StringBuilder sb = new StringBuilder(len);
        for (int i = 0; i < len; i++) {
            char c = param.charAt(i);
            if (c == UNDERLINE) {
                if (++i < len) {
                    sb.append(Character.toUpperCase(param.charAt(i)));
                }
            } else {
                sb.append(c);
            }
        }
        return sb.toString();
    }

    /**
     *
     * @param obj
     * @param id
     * @param parentId
     * @return
     */
    static List listParentByChild(Object child, String parentId ){
        def result = []
        childFindParent(child,parentId,result)
        return  result
    }

    /**
     * 通过父节点，找子节点
     * @param parent
     * @param list
     * @param id
     * @param parentId
     * @return
     */
    static List listChildByParent(Object parent,List list,String id,  String parentId ){
        def result = []
        parentFindChild( parent, list,  id,   parentId,  result)
        return  result
    }

    /**
     *子节点找父节点
     * @param child
     * @param parentId
     * @param result
     * @return
     */
    static childFindParent(Object child, String parentId,List result){
        result.add(child)
        if(child."${parentId}"){
            def parent = child.getClass().get(child."${parentId}")
            childFindParent(parent,parentId,result)
        }
    }

    /**
     * 父节点：找子节点
     * @param parent
     * @param list
     * @param id
     * @param parentId
     * @param result
     * @return
     */
    static parentFindChild(Object parent,List list,String id, String parentId,List result){
        result.add(parent)
        def copyList = list.toList()
        list.each {
            if(it."${parentId}" == parent."${id}"){
                result.add(it)
                copyList.remove(it)
                parentFindChild(it,copyList,id,parentId,result)
            }
        }
    }

    /**
     * java.sql.Clob 转 String
     * @param clob
     * @return
     */
    static Clob2String(Clob clob){
        StringBuffer stringBuffer = new StringBuffer("")

        if(clob){
            Reader reader =  clob.getCharacterStream()
            BufferedReader bufferedInputStream = new BufferedReader(reader)
//            println "bufferedInputStream.ready():${bufferedInputStream.ready()}"
            def s = bufferedInputStream.readLine()
            while (s!=null){
                stringBuffer.append(s)
                s = bufferedInputStream.readLine()
            }
            bufferedInputStream.close()
            reader.close()
        }
        return stringBuffer.toString()
    }

    /**
     * String 转 java.sql.Clob
     * @param str
     * @return
     */
    static String2Clob(String str){
        if(!str){
            str = ""
        }
       return  new javax.sql.rowset.serial.SerialClob(str.toCharArray())
    }

    /**
     * 返回当前时间毫秒数
     * @return
     */
    static milliseconds(){
        return  new Date().getTime()
    }

    /**
     * 判定是否为数字
     * @param obj
     * @return
     */
    static isDigit(obj){
        def str = String.valueOf(obj).trim()
        try {
            BigDecimal bigDecimal = new BigDecimal(str)
            bigDecimal = null
            return true
        }catch (Exception e){
            return  false
        }
    }


    /**
     * 查询总记录数
     * @param sql
     * @param db
     * @return
     */
    public static  pageCount(String sql,groovy.sql.Sql db){
        def cSql = """
            select count(1) COUNTN FROM ( ${sql} ) A
        """
        return db.firstRow(String.valueOf(cSql)).COUNTN?:0
    }
    /**
     * 根据SQL获取分页数据
     * @param sql
     * @param offset start with 1
     * @param max
     * @param db
     * @return
     */
     static pageResult(sql ,int offset,int max,groovy.sql.Sql db){
         def dsn = db.getDataSource()?:db.getConnection()
         Dialect dialect = Dialect.guessDialect(dsn)
         sql = dialect.paginAndTrans(offset,max,String.valueOf(sql))
         dialect = null
         return db.rows(sql)
    }

    /**
     * 根据DB，获取数据库方言
     * @param db
     * @return
     */
    static getDialect(db){
        def dsn = db.getDataSource()?:db.getConnection()
        Dialect dialect = Dialect.guessDialect(dsn)
        def type = String.valueOf(dialect.name()).toUpperCase()
        if(type.indexOf("ORACLE")){
            type = "ORACLE"
        }
        return  type
    }

    /**
     * 获取所有数据,不分页
     * @param sql
     * @param db
     * @return
     */
    static pageAllResult(String sql,groovy.sql.Sql db){
        return db.rows(String.valueOf(sql))
    }

    static createUUID(){
        return java.util.UUID.randomUUID().toString()
    }
    /**
     * 创建临时文件
     * @param suffix
     * @return
     */
    static File createTempFile(String suffix){
        return File.createTempFile("XD-SYSADMIN-TMP-",suffix)
    }

    /**
     * 获取临时文件
     * @param fileName
     */
    static File getTempFile(String fileName){
        return new File(System.getProperty(TempFile.JAVA_IO_TMPDIR),fileName)
    }

    /**
     * 解决文件下载乱码问题
     * @param request
     * @param fileName
     */
    static String EncodingFileName(HttpServletRequest request ,String fileName){
        String newFile = ""
        String userAgent = request.getHeader("user-agent").toLowerCase();
        if (userAgent.contains("msie") || userAgent.contains("like gecko") ) {
            // win10 ie edge 浏览器 和其他系统的ie
            newFile = URLEncoder.encode(fileName, "UTF-8");
        } else {
            // fe
            newFile = new String(fileName.getBytes("utf-8"), "iso-8859-1");
        }
        return newFile
    }

    /**
     * 合并2个有效的html到rpt表的的body
     * @param fromStr
     * @param toStr
     */
    static parseHTMLRptTemp2Act(String fromHtml ,String toStr){
        Document doc = Jsoup.parseBodyFragment(fromHtml);
    }

    /**
     * 字符串转日期
     * @param dateStr
     */
    static parseString2Date(dateStr){

        Date date
        boolean  flag = true
        SimpleDateFormat format = new SimpleDateFormat(DateFormat_YYYYMMDD_hh24miss);
        try {
            date = format.parse(dateStr)
        }catch (Exception e){
            println "${dateStr}  convert to date is error! --- 1"
            flag = false
        }

        if(flag == false){
            try {
                format = new SimpleDateFormat(DateFormat_YYYYMMDD);
                date = format.parse(dateStr)
                flag == true
            }catch (Exception e1){
                println "${dateStr}  convert to date is error! --- 2"
            }
        }

        if(flag == false){
            try {
                format = new SimpleDateFormat(DateFormat_YYYYMM);
                date = format.parse(dateStr)
                flag == true
            }catch (Exception e1){
                println "${dateStr}  convert to date is error! --- 3"
            }
        }
        return date
    }

    /**
     * 对象转json
     * @param jsonStr
     * @return
     */
    static parseObj2Json(jsonStr){
        if(jsonStr && String.valueOf(jsonStr).length()!=0){
            return net.sf.json.JSONObject.fromObject(jsonStr)
        }
        return new net.sf.json.JSONObject()
    }

    /**
     * 获取项目部署的路径
     */
    static getProjectPath(){
        return SysInitData.WEB_REAL_PATH;
    }

    /**
     * 根据文件ID标识获取文件
     * @param id
     * @return
     */
    static getEchartTempleteXMLFile(fileID){
        def filePath = "${getProjectPath()}\\echartsResource\\templete\\${fileID}.xml"
        def file = new File(filePath)
        if(!file.exists()){
            file.createNewFile()
            def modelFile = new File("${getProjectPath()}\\echartsResource\\model\\echart-pub-opt.xml")
            def panelId = Long.parseLong(String.valueOf(fileID))
            XdWidgetPanel panel = XdWidgetPanel.get(panelId)
            XdWidget xdWidget = XdWidget.get(panel.xdWidgetId)
            def seriesFile = new File("${getProjectPath()}\\echartsResource\\model\\${xdWidget.classFlag}.xml")
            file.write("<body>${modelFile.getText()}${seriesFile.getText()}</body>")
        }
        return file
    }



    /**
     * 获取Echart预览option
     */
    static getTempEchartOptByXml(sourceXml){
        def jsoup = JsoupUtil.getJsoupInstanceFromDom(sourceXml)
        def tempoption = jsoup.selectFirst("tempoption").html()
        def tempoptionvalue =  SysCommUtil.parseObj2Json(jsoup.selectFirst("tempoptionvalue").html())
        tempoption = BeetlUtil.getStrTemplate(tempoptionvalue,tempoption)
        return   SysCommUtil.parseObj2Json(tempoption)
    }


    /**
     * 根据node（按照node 名称唯一）
     * sourceXml 为输入的xml源
     * @param source
     * @param nodeName
     */
    static getJSONStrByNode(sourceXml,nodeName){
        def jsoup = JsoupUtil.getJsoupInstanceFromDom(sourceXml)
        def tempoption = jsoup.selectFirst(nodeName)?.html()?:""
        return   tempoption
    }


    /**
     * 根据node（按照node 名称唯一）
     * sourceXml 为输入的xml源
     * @param source
     * @param nodeName
     */
    static getJSONByNode(sourceXml,nodeName){
        return   SysCommUtil.parseObj2Json(getJSONStrByNode(sourceXml,nodeName))
    }

    /**
     * 获取echart 交互属性配置
     * @param sourceXml
     */
    static getEchartActionParamByXml(sourceXml){
        def tempoptionValue = SysCommUtil.getJSONByNode(sourceXml,"tempoptionvalue")
        def actionParam = SysCommUtil.getJSONByNode(sourceXml,"action")
        actionParam.put("queryFlag",Boolean.parseBoolean(tempoptionValue.get("queryFlag")))
        actionParam.put("autoFlag", Boolean.parseBoolean(tempoptionValue.get("autoFlag")))
        actionParam.put("autoInterval",tempoptionValue.get("autoInterval"))
        actionParam.put("echartAction",tempoptionValue.get("echartAction"))
        actionParam.put("height",tempoptionValue.get("height")?:80)
        return actionParam
    }

}

